﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;

using Windows.Networking;
using Windows.Networking.Sockets;
using Windows.Storage.Streams;
using Windows.System.Threading;

namespace Pear.Net
{
    class Net : IDisposable
    {
        private HostName hostname;
        private string port;
        private string status;
        private bool isOnline;
        private StreamSocket ss;
        private List<String> output;
        private List<String> input;
        private List<String> show;
        private DataWriter writer;
        private DataReader reader;
        

        public Net(string hostname, string port)
        {
            this.hostname = new HostName(hostname);
            this.port = port;
            this.status = "";
            this.isOnline = false;
            // 这里就在初始化socket
            this.ss = new StreamSocket();

            this.output = new List<String>();
            this.input = new List<String>();
            this.show = new List<String>();
            this.writer = new DataWriter(ss.OutputStream);
            this.reader = new DataReader(ss.InputStream);
        }

        public async void connect()
        {
            if (isOnline)
            {
                status = "Already Connecting";
                return;
            }
            try
            {
                this.status = "Trying to connect ...";
                await ss.ConnectAsync(hostname, port);
                this.isOnline = true;
                status = "Connection established" + Environment.NewLine;
            }
            catch (Exception ex)
            {
                // If this is an unknown status, 
                // it means that the error is fatal and retry will likely fail.
                if (SocketError.GetStatus(ex.HResult) == SocketErrorStatus.Unknown)
                {
                    throw;
                }

                this.status = "Connect failed with error: " + ex.Message;
                // Could retry the connection, but for this simple example
                // just close the socket.

                // the Close method is mapped to the C# Dispose
                this.ss.Dispose();
                this.ss = null;
            }
        }

        public async void send(String sendData)
        {
            if (!isOnline)
            {
                this.status = "Must be connected to send!";
                return;
            }

            Int32 len = 0; // Gets the UTF-8 string length.

            try
            {

                this.status = "Trying to send data ...";

                // add a newline to the text to send
                string str = sendData + Environment.NewLine;

                len = (Int32)writer.MeasureString(str); // Gets the UTF-8 string length.
                writer.WriteString(str);

                // Call StoreAsync method to store the data to a backing stream
                await writer.StoreAsync();

                this.status = "Data was sent" + Environment.NewLine;

                // detach the stream and close it
                //writer.DetachStream();
                //writer.Dispose();

            }
            catch (Exception exception)
            {
                // If this is an unknown status, 
                // it means that the error is fatal and retry will likely fail.
                if (SocketError.GetStatus(exception.HResult) == SocketErrorStatus.Unknown)
                {
                    throw;
                }

                this.status = "Send data or receive failed with error: " + exception.Message;
                // Could retry the connection, but for this simple example
                // just close the socket.

                
                ss.Dispose();
                ss = null;
                this.isOnline = false;

            }


        }

        public async Task<String> receive()
        {
            // Now try to receive data from server
            try
            {
                this.status = "Trying to receive data ...";


                // Set inputstream options so that we don't have to know the data size
                reader.InputStreamOptions = InputStreamOptions.Partial;

                await reader.LoadAsync(reader.UnconsumedBufferLength);

            }
            catch (Exception exception)
            {
                // If this is an unknown status, 
                // it means that the error is fatal and retry will likely fail.
                if (SocketError.GetStatus(exception.HResult) == SocketErrorStatus.Unknown)
                {
                    throw;
                }

                this.status = "Receive failed with error: " + exception.Message;
                // Could retry, but for this simple example
                // just close the socket.

                
                ss.Dispose();
                ss = null;
                isOnline = false;

            }
            return String.Empty;
        }
        public void Dispose()
        {
            try
            {
                ss.Dispose();
                ss = null;
                writer.Dispose();
                writer = null;
                reader.Dispose();
                reader = null;
            }
            catch (Exception)
            {

                throw;
            }
        }
    }
}
